#include "mqtt_config.h"
#include "mqtt_manager.h"
#include "mqtt_message_handler.h"
#include "cJSON.h"
#include "mqtt_cmd.h"
#include "mqtt_cb.h"
#include "ota.h"

#define EVENT_TASK_NAME "mqttProc"               /*!< 任务名称 */
#define EVENT_TASK_STACK (3 * 1024)             /*!< 任务栈大小 */
#define EVENT_TASK_PRIORITY (10)                /*!< 任务优先级 */
#define EVENT_QUEUE_SIZE (10)                   /*!< 任务队列大小 */

#define SERVER_RESPONSE_CODE_OK      (0)                /*!< 云端响应成功错误码 */
#define SERVER_RESPONSE_CODE_ERROR   (3006)             /*!< 云端响应失败错误码:Json格式错误 */

static QueueHandle_t g_queue_hd = NULL;         /*!< 事件队列句柄 */
static esp_mqtt_client_handle_t g_client_hd;    

static const char *TAG = "MQTT_MSG_HD";

void initMqttClientHandle(esp_mqtt_client_handle_t client)
{
    g_client_hd = client;
}
static void mqttSendCommandResponse(esp_mqtt_client_handle_t client, char *header_name, char *request_id)
{
    // 创建 JSON 根对象
    cJSON *root = cJSON_CreateObject();
    if (root == NULL) {
        ESP_LOGE(TAG, "Failed to create root object");
        return;
    }

    // 创建 "header" 对象
    cJSON *header = cJSON_CreateObject();
    if (header == NULL) {
        ESP_LOGE(TAG, "Failed to create header object");
        cJSON_Delete(root);
        return;
    }

    // 填充 header 部分
    cJSON_AddStringToObject(header, "namespace", "com.lockly");
    cJSON_AddStringToObject(header, "name", header_name);
    cJSON_AddStringToObject(header, "requestId", request_id);
    cJSON_AddNumberToObject(header, "timestamp", 1645584206);

    // 将 header 添加到根对象
    cJSON_AddItemToObject(root, "header", header);

#if 0
    if (!strcmp(header_name, "hubCommandResponse")) {
        // 构建 "payload" 对象
        cJSON *payload = cJSON_CreateObject();
        if (payload == NULL) {
            ESP_LOGE(TAG, "Failed to create payload object");
            cJSON_Delete(root);
            return;
        }

        cJSON_AddStringToObject(payload, "code", "0");

        // 构建 "commandContent" 对象
        cJSON *command_content = cJSON_CreateObject();
        if (command_content == NULL) {
            ESP_LOGE(TAG, "Failed to create commandContent object");
            cJSON_Delete(root);
            return;
        }

        cJSON_AddStringToObject(command_content, "cod", "200");
        cJSON_AddStringToObject(command_content, "toDevice", "M23T20001296T");

        // 构建 "data" 对象
        cJSON *data = cJSON_CreateObject();
        if (data == NULL) {
            ESP_LOGE(TAG, "Failed to create data object");
            cJSON_Delete(root);
            return;
        }

        cJSON_AddStringToObject(data, "req_msg_id", "1856968193063544833");
        cJSON_AddStringToObject(data, "ref", "32,200024003131471239333532,L,PGD728FN");
        cJSON_AddStringToObject(data, "addr", "01:01:33:32:2c:32");
        cJSON_AddStringToObject(data, "m2m_rpt", "Y");
        cJSON_AddStringToObject(data, "ACK", "A1B2C3D419000A22AB1B75C5D69BCB0DFC49BDB4A310698C98");

        // 添加嵌套对象
        cJSON_AddItemToObject(command_content, "data", data);
        cJSON_AddItemToObject(payload, "commandContent", command_content);

        cJSON_AddItemToObject(root, "payload", payload);
    }
#endif

    // 将 JSON 对象转为字符串
    char *message = cJSON_PrintUnformatted(root);
    if (message == NULL) {
        ESP_LOGE(TAG, "Failed to print JSON message");
        cJSON_Delete(root);
        return;
    }

    // 发布消息到主题
    int msg_id = esp_mqtt_client_publish(client, "server", message, 0, 1, 0);
    ESP_LOGI(__func__, "Sent message with ID: %d\n", msg_id);

    // 释放动态分配的 JSON 字符串
    free(message);

    // 释放 JSON 根对象及其子对象
    cJSON_Delete(root);
}

static void mqttSendDateReport(esp_mqtt_client_handle_t client, char *message, char *msg_id)
{
    // 创建 JSON 对象
    cJSON *root = cJSON_CreateObject();

    // 构建 "header" 对象
    cJSON *header = cJSON_CreateObject();
    cJSON_AddStringToObject(header, "namespace", "com.lockly");
    cJSON_AddStringToObject(header, "name", "deviceInfoReport");
    cJSON_AddStringToObject(header, "requestId", "b3df88a6-1438-4f68-a9e7-5e95b95e39c2");
    cJSON_AddNumberToObject(header, "timestamp", 1645584206);

    // 构建 "payload" 对象
    cJSON *payload = cJSON_CreateObject();
    cJSON_AddStringToObject(payload, "deviceId", "PGH230U22012796T");

    // 将原有 上报;阿里云 的 协议 打包在  commandContent 中
    cJSON_AddItemToObject(payload, "commandContent", cJSON_Parse(message));

    cJSON_AddItemToObject(root, "header", header);
    cJSON_AddItemToObject(root, "payload", payload);

    // 将 JSON 转为字符串
    char *json_string = cJSON_PrintUnformatted(root);

    // 发布消息到指定主题
    int esp_msg_id = esp_mqtt_client_publish(client, "server", json_string, 0, 1, 0);
    ESP_LOGI(__func__, "Message sent, msg_id=%d", esp_msg_id);

    // 释放 JSON 对象
    cJSON_Delete(root);
    free(json_string);
}

static void mqttSendDateRespond(esp_mqtt_client_handle_t client, char *message, char *msg_id)
{
    // 创建 JSON 对象
    cJSON *root = cJSON_CreateObject();

    // 构建 "header" 对象
    cJSON *header = cJSON_CreateObject();
    cJSON_AddStringToObject(header, "namespace", "com.lockly");

    cJSON_AddStringToObject(header, "name", "hubCommandResponse");

    cJSON_AddStringToObject(header, "requestId", "b3df88a6-1438-4f68-a9e7-5e95b95e39c2");
    cJSON_AddNumberToObject(header, "timestamp", 1645584206);

    // 构建 "payload" 对象
    cJSON *payload = cJSON_CreateObject();
    cJSON_AddStringToObject(payload, "code", "0");

    // 将原有 上报;阿里云 的 协议 打包在  commandContent 中
    cJSON_AddItemToObject(payload, "commandContent", cJSON_Parse(message));

    cJSON_AddItemToObject(root, "header", header);
    cJSON_AddItemToObject(root, "payload", payload);

    // 将 JSON 转为字符串
    char *json_string = cJSON_PrintUnformatted(root);
    // 发布消息到指定主题
    int esp_msg_id = esp_mqtt_client_publish(client, "server", json_string, 0, 1, 0);
    ESP_LOGI(__func__, "Message sent, msg_id=%d", esp_msg_id);

    // 释放 JSON 对象
    cJSON_Delete(root);
    free(json_string);
}

static char *cloudCtrlExeCmd(esp_mqtt_client_handle_t client, char *data, char *msg_id)
{
    RespServEvtMsg resp_msg = {0};

    // 解析 JSON 字符串
    cJSON *root = cJSON_Parse(data);
    if (!root)
    {
        ESP_LOGE(TAG, "Error parsing JSON");
        resp_msg.error_code = SERVER_RESPONSE_CODE_ERROR;
        // TODO:回复错误解析状态
        return;
    }

    // 定位到 header 对象
    cJSON *header = cJSON_GetObjectItem(root, "header");
    if (header == NULL)
    {
        ESP_LOGE(TAG, "Header not found\n");
        cJSON_Delete(root); // 释放 root
        // TODO:回复错误解析状态
        return;
    }

    // 定位到 payload 对象
    cJSON *payload = cJSON_GetObjectItem(root, "payload");
    if (payload == NULL)
    {
        ESP_LOGE(TAG, "Payload not found\n");
        cJSON_Delete(root); // 释放 root
        // TODO:回复错误解析状态
        return;
    }

    // 提取 requestId
    cJSON *request_id = cJSON_GetObjectItem(header, "requestId");
    if (cJSON_IsString(request_id) && (request_id->valuestring != NULL))
    {
        printf("Request ID: %s\n", request_id->valuestring);
    }
    else
    {
        printf("Request ID not found\n");
    }

    // 提取 name
    cJSON *name = cJSON_GetObjectItem(header, "name");
    if (cJSON_IsString(name) && (name->valuestring != NULL))
    {
        if (!strcmp(name->valuestring, "ping"))
        {
            ESP_LOGI(TAG, "get ping");
            mqttSendCommandResponse(client, "pong", request_id->valuestring); // 回复 pong
            
            cJSON *time_stamp = cJSON_GetObjectItem(header, "timestamp");
            ESP_LOGI("yuezheng.gao","time_stamp = %d",time_stamp->valueint);
            if(time_stamp->valueint == 999999999)
            {
                ESP_LOGI("yuezheng.gao","start OTA test");

                #if 0
                start_ota_test();
                #else
                // {"cmd":"ota","release_name":"PGH230U_MQ_V5.0.01.1","server_name":"http://54.70.166.15/firmware/","file_name":"PGH230U_MQ_V5.0.01.1.bin","md5":"6DA9A693F24045B63D26244323142B24","ver":"5.0.01.1","fromDevice":"M23T20000006T"}
                const char *json_message = "{\"cmd\":\"ota\",\"release_name\":\"PGH230U_MQ_V5.0.01.1\",\"server_name\":\"http://54.70.166.15/firmware/\",\"file_name\":\"PGH230U_MQ_V5.0.01.1.bin\",\"md5\":\"6DA9A693F24045B63D26244323142B24\",\"ver\":\"5.0.01.1\",\"fromDevice\":\"M23T20000006T\"}";
                size_t data_len = 0;
                bool reply_in_cb_func = false;
                char *payload_data = exec_cmd(json_message, strlen(json_message), &data_len, client, "1869997960150934528", &reply_in_cb_func);
                if (payload_data)
                {
                    free(payload_data);
                }
                #endif


            }
        }
        else if (!strcmp(name->valuestring, "hubCommandRequest"))
        {
            ESP_LOGI(TAG, "get hubCommandRequest");
            // 获取 commandContent 对象
            cJSON *commandContent = cJSON_GetObjectItem(payload, "commandContent");

            if (commandContent != NULL)
            {
                char *commandContentStr = cJSON_PrintUnformatted(commandContent);
                if (commandContentStr != NULL)
                {
                    size_t data_len = 0;
                    bool reply_in_cb_func = false;
                    hub_working_code_t curr_mode =  get_curr_working_mode();
                    
                    // TODO:msg_id 这个参数 后续斟酌是否需要或如何传入
                    char *res = exec_cmd(commandContentStr, strlen(commandContentStr), &data_len, client, "1869997960150934528", &reply_in_cb_func);
                    
                    if (!reply_in_cb_func)
                    {
                        if (res == NULL)
                        {
                            switch (curr_mode)
                            {
                            case INIT_MODE:
                                // ESP_LOGE(TAG,"Should not be executed!!!");
                                break;
                            case MQTT_MODE:{
                                // char data[] = JSON_STR_INVALID_PARA_ERR;
                                char *data = malloc(strlen(JSON_STR_INVALID_PARA_ERR) + 1);
                                strcpy(data, JSON_STR_INVALID_PARA_ERR);
                                data_len = strlen(data);
                                ESP_LOGW("yuezheng.gao","parameter error");
                                // free(data);
                                }
                            break;
                            case BLUFI_MODE:{
                                char *data = malloc(strlen(JSON_STR_BLUFI_MODE_ERR) + 1);
                                // char data[] = JSON_STR_BLUFI_MODE_ERR;
                                strcpy(data, JSON_STR_BLUFI_MODE_ERR);
                                data_len = strlen(data);
                                // free(data);
                                }
                            break;
                            case OTA_MODE:{
                                // char data[] = JSON_STR_OTA_MODE_ERR;
                                char *data = malloc(strlen(JSON_STR_OTA_MODE_ERR) + 1);
                                strcpy(data, JSON_STR_OTA_MODE_ERR);
                                data_len = strlen(data);
                                // free(data);
                                }
                            }
                        }
                        mqtt_cb_cmd_t cb_cmd_main;
                        memset(&cb_cmd_main, 0x0, sizeof(mqtt_cb_cmd_t));
                        cb_cmd_main.topic_type = RRPC;
                        strcpy(cb_cmd_main.msg_id, msg_id);
                        cb_cmd_main.payload_data = data;
                        cb_cmd_main.data_len = data_len;
                        cb_cmd_main.need_free_buf = true;
                        mqtt_cb_enqueue(&cb_cmd_main);
                    }
                    if(commandContentStr)
                    {
                        free(commandContentStr);
                    }
                    return res;
                    
                }
                else
                {
                    ESP_LOGE(TAG, "Failed to serialize commandContent");
                }
            }
            else
            {
                ESP_LOGE(TAG, "commandContent not found");
            }
        }
    }
    else
    {
        ESP_LOGE(TAG, "Invalid or missing 'name' in header");
        // TODO:上报 name 解析错误的消息
    }

    // 释放 JSON 根对象
    cJSON_Delete(root);
    return NULL;
}

bool deviceEvtPost(EvenType event_type,cb_topic_type_t topic_type,void *mqtt_data, int32_t mqtt_data_size,char* mqtt_msg_id)
{
    EvtMsg msg = {0};

    if (!g_queue_hd)
    {
        ESP_LOGW(TAG, "queue is NULL");
        return false;
    }

    // 数据下行 时 申请一段 空间截取有效数据
    if (event_type == MQTT_DOWN_STREAM)
    {
        if (mqtt_data)
        {
            msg.data = (void *)calloc(1, mqtt_data_size + 1);
            if (!msg.data)
            {
                return false;
            }

            memcpy(msg.data, mqtt_data, mqtt_data_size);
        }
        else
        {
            msg.data = NULL;
        }
    }
    // 数据上行，已经在堆区动态申请过了，不需要重新申请
    else if(event_type == MQTT_UP_STREAM)
    {
        msg.data = mqtt_data;
    }

    msg.size = mqtt_data_size;
    msg.msg_id = mqtt_msg_id;
    msg.event_type = event_type;
    msg.topic_type = topic_type;
    if (xQueueSendToBack(g_queue_hd, &msg, 100) != pdPASS)
    {
        ESP_LOGW(TAG, "post evt failed");
        if (msg.data)
        {
            free(msg.data);
        }
        return false;
    }

    return true;
}

/**
 * @brief   应用层事件处理任务
 * 
 * @param[in]   pv 任务参数
 * 
 */
static void mqttEventHandler(void *pv)
{   
    EvtMsg event_msg = {0};
    char *res = NULL;
    while (true)
    {
        memset(&event_msg, 0, sizeof(event_msg));

        if (xQueueReceive(g_queue_hd, &event_msg, portMAX_DELAY) == pdPASS)
        {
            ESP_LOGW(TAG, " mqttEventHandler event_type = %d  dataLen = %d  data = %s\r\n",event_msg.event_type,event_msg.size, event_msg.data);
            if(event_msg.event_type == MQTT_DOWN_STREAM)
            {
                // 处理mqtt请求
                res = cloudCtrlExeCmd(g_client_hd,event_msg.data,event_msg.msg_id);
            }
            else if(event_msg.event_type == MQTT_UP_STREAM)
            {
                if(event_msg.topic_type >= LOCK_REPORT)
                {
                    // 主动上报数据
                    mqttSendDateReport(g_client_hd,event_msg.data,event_msg.msg_id);
                }
                else
                {
                    // 响应请求数据
                    mqttSendDateRespond(g_client_hd,event_msg.data,event_msg.msg_id);
                }
            }
            
        }

        if(event_msg.data)
        {
            free(event_msg.data);
        }
        if(res)
        {
            free(res);
        }
        
        
    }
}

void createMqttEvtTaskAndQueue(void)
{
    g_queue_hd = xQueueCreate(EVENT_QUEUE_SIZE, sizeof(EvtMsg));
    
    if (!g_queue_hd)
    {
        ESP_LOGE(TAG, "app queue create failed");
    }

    if (xTaskCreate(mqttEventHandler, EVENT_TASK_NAME, EVENT_TASK_STACK, NULL, EVENT_TASK_PRIORITY, NULL) != pdPASS)
    {
        ESP_LOGE(TAG, "devEventHandler task create failed");
    }
    return 0;
}